﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Runtime.Serialization;
using System.Security.Cryptography;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using UnwiseSourceService.Models;
using UnwiseSourceService.ToolClasses;
using UnwiseSourceService.ToolClasses.AdminClasses;

namespace UnwiseSourceService
{
    public class Service1 : IService1
    {
        private static string getconfigparam(string pname, string defaultvalue = "")
        {
            try
            {
                object ov = ConfigurationManager.AppSettings[pname];
                return ov.ToString();
            }
            catch (Exception ex)
            {
                Logger.LoggError(ex);
                return defaultvalue;
            }
        }
        
        //Not in the Interface
        public bool ValidAccesskey(string accessKey)
        {
            string key = getconfigparam("SECID", "");
            if (key != "")
            {
                if (accessKey == key)
                {
                    return true;
                }
            }

            return false;
        }

        public Quotes ReadAQuote(string accessKey, int quoteNumber)
        {
            if (ValidAccesskey(accessKey))
            {
                try
                {
                    using (unwisesourceEntities entity = new unwisesourceEntities())
                    {
                        int quotesCount = entity.Quotes.Count();
                        int findQuote = quoteNumber % (quotesCount + 1);

                        if (findQuote == 0)
                        {
                            findQuote = 1;
                        }

                        Quotes quote = entity.Quotes.FirstOrDefault((i) => i.QuoteNumber == findQuote);

                        return quote;
                    }
                }
                catch (Exception exc)
                {
                    Logger.LoggError(exc);
                }
            }
         
            return null;
        }

        public List<v_Courses> GetCourses(string accessKey, string language)
        {
            if (ValidAccesskey(accessKey))
            {
                try
                {
                    using(unwisesourceEntities entity = new unwisesourceEntities())
                    {
                        var courses =
                            from course in entity.v_Courses
                            where course.Language == language
                            select new
                            {
                                Course = course,
                                Lectors = from user in entity.Users
                                          join contributor in entity.CoursesContributors
                                          on user.UserId equals contributor.UserId
                                          where contributor.Lector == true && contributor.CourseId == course.CourseId
                                          select user.Name
                            };

                        List<v_Courses> result = new List<v_Courses>();
                        foreach (var item in courses)
                        {
                            item.Course.Lectors = item.Lectors.ToList();
                            result.Add(item.Course);
                        }

                        return result;
                    }
                }
                catch (Exception exc)
                {
                    Logger.LoggError(exc);
                }
            }

            return null;
        } 

        public bool CreateCourse (string accessKey, Courses course)
        {
            if (ValidAccesskey(accessKey))
            {
                using (unwisesourceEntities entity = new unwisesourceEntities())
                {
                    try
                    {
                        entity.Courses.Add(course);
                        entity.SaveChanges();
                    }
                    catch (Exception exc)
                    {
                        Logger.LoggError(exc);
                        return false;
                    }

                    return true;
                }
            }

            return false;
        }

        public List<v_Lectures> GetLectures(string accessKey, string language)
        {
            if (ValidAccesskey(accessKey))
            {
                try
                {
                    using (unwisesourceEntities entity = new unwisesourceEntities())
                    {
                        var lectures =
                            from lecture in entity.v_Lectures
                            where lecture.Language == language
                            select lecture;

                        return lectures.ToList();
                    }
                }
                catch (Exception exc)
                {
                    Logger.LoggError(exc);
                }
            }

            return null;
        }

        public LecturesAndHeader GetLecturesOfCourse(string accessKey, string language, int courseId)
        {
            if (ValidAccesskey(accessKey))
            {
                try
                {
                    using (unwisesourceEntities entity = new unwisesourceEntities())
                    {
                        var lectures =
                            from lecture in entity.v_Lectures
                            where (lecture.CourseId == courseId) && (lecture.Language == language)
                            select lecture;

                        LecturesAndHeader result = new LecturesAndHeader();
                        result.Lectures = lectures.ToList();

                        //no check because of the catch
                        result.CourseHeader = entity.v_Courses.FirstOrDefault(c => c.CourseId == courseId && 
                            c.Language == language).CourseName;

                        return result;
                    }
                }
                catch (Exception exc)
                {
                    Logger.LoggError(exc);
                }
            }

            return null;
        }

        public UserCredibility LogIn (string accessKey, Users user)
        {
            if (ValidAccesskey(accessKey))
            {
                try
                {
                    using (unwisesourceEntities entity = new unwisesourceEntities())
                    {
                        v_Users foundUser = entity.v_Users.FirstOrDefault(u =>
                            u.Username == user.Username && u.Password == user.Password);

                        if (foundUser != null)
                        {
                            UserCredibility creds = new UserCredibility(foundUser.RoleName);
                            creds.Credible = true;
                            creds.UserId = foundUser.UserId;
                            creds.Username = foundUser.Username;
                            creds.Name = foundUser.Name;
                            return creds;
                        }
                    }
                }
                catch (Exception exc)
                {
                    Logger.LoggError(exc);
                }
            }

            return new UserCredibility();
        }

        public List<AdminCourse> GetAdminCourses(string accessKey, string language)
        {
            if (ValidAccesskey(accessKey))
            {
                try
                {
                    using (unwisesourceEntities entity = new unwisesourceEntities())
                    {
                        var adminCourses =
                            from course in entity.v_Courses
                            where course.Language == language
                            select new
                            {
                                CourseId = course.CourseId,
                                CourseName = course.CourseName,
                                Creator = entity.CoursesContributors.FirstOrDefault(c => c.CourseId == course.CourseId &&
                                    c.Contributions.ContributionName == "Owner").Users.Name,
                                CreatorId = entity.CoursesContributors.FirstOrDefault(c => c.CourseId == course.CourseId &&
                                    c.Contributions.ContributionName == "Owner").Users.UserId,
                                Created = course.Created,
                                Modified = course.Modified,
                                Modifier = entity.Users.FirstOrDefault(u => u.UserId == course.LastActionBy).Username,
                                NumberOfLectures = entity.Lectures.Count(l => l.CourseId == course.CourseId),
                                EndDate = course.EndDate,
                                Contributors = 
                                    from contributor in entity.CoursesContributors
                                    where contributor.CourseId == course.CourseId
                                    select contributor.UserId
                            };

                        List<AdminCourse> result = new List<AdminCourse>();

                        foreach (var item in adminCourses)
                        {
                            AdminCourse course = new AdminCourse();
                            course.CourseId = item.CourseId;
                            course.CourseName = item.CourseName;
                            course.Creator = item.Creator;
                            course.CreatorId = item.CreatorId;
                            course.Created = item.Created;
                            course.Modifier = item.Modifier;
                            course.Modified = item.Modified;
                            course.NumberOfLectures = item.NumberOfLectures;
                            course.Contributors = item.Contributors.ToList();

                            //check if it is ongoing
                            if (item.EndDate != null)
                            {
                                var difference = DateTime.Now.CompareTo(item.EndDate);

                                if (difference > 0)
                                {
                                    course.Ended = true;
                                }
                                else
                                {
                                    course.Ended = false;
                                }
                            }

                            result.Add(course);
                        }

                        return result;
                    }
                }
                catch (Exception exc)
                {
                    Logger.LoggError(exc);
                }
            }


            return null;
        }

        public bool DeleteCourse(string accessKey, int courseId)
        {
            if (ValidAccesskey(accessKey))
            {
                try
                {
                    using (unwisesourceEntities entity = new unwisesourceEntities())
                    {
                        Courses course = entity.Courses.Find(courseId);
                        entity.Courses.Remove(course);
                        entity.SaveChanges();

                        return true;
                    }
                }
                catch (Exception exc)
                {
                    Logger.LoggError(exc);
                }
            }

            return false;
        }
    
        public FullCourse GetFullCourse(string accessKey, int courseId)
        {
            if (ValidAccesskey(accessKey))
            {
                try
                {
                    using (unwisesourceEntities entity = new unwisesourceEntities())
                    {
                        var queryCourse = 
                            from course in entity.Courses
                            where course.CourseId == courseId
                            select new 
                            {
                                Id = course.CourseId,
                                Alias = course.CourseAlias,
                                LevelId = course.LevelId,
                                StartDate = course.StartDate,
                                EndDate = course.EndDate,
                                LecturesPerWeek = course.LecturesPerWeek,

                                Names = 
                                    from cName in course.CoursesNames
                                    select new
                                    {
                                        Name = cName.CourseName,
                                        Language = cName.Language
                                    },
                                Summaries = 
                                    from cSummary in course.CoursesSummaries
                                    select new
                                    {
                                        Summary = cSummary.SummaryContent,
                                        Language = cSummary.Language
                                    },
                                Contributors = 
                                    from cContributor in course.CoursesContributors
                                    select new
                                    {
                                        UserId = cContributor.UserId,
                                        Name = cContributor.Users.Name,
                                        Username = cContributor.Users.Username,
                                        Contribution = cContributor.Contributions.ContributionName,
                                        Lector = cContributor.Lector
                                    }
                            };

                        var foundCourses = queryCourse.ToList();
                        if (foundCourses.Count == 1)
                        {
                            var foundCourse = foundCourses[0];
                            FullCourse fullCourse = new FullCourse();

                            fullCourse.Id = foundCourse.Id;
                            fullCourse.Alias = foundCourse.Alias;
                            fullCourse.LevelId = foundCourse.LevelId;
                            fullCourse.StartDate = foundCourse.StartDate;
                            fullCourse.EndDate = foundCourse.EndDate;
                            if (foundCourse.LecturesPerWeek != null)
                            {
                                fullCourse.LecturesPerWeek = foundCourse.LecturesPerWeek.Value;
                            }

                            foreach (var item in foundCourse.Names)
                            {
                                MultiLingual name = new MultiLingual();
                                name.Language = item.Language;
                                name.Value = item.Name;

                                fullCourse.Names.Add(name);
                            }

                            foreach (var item in foundCourse.Summaries)
                            {
                                MultiLingual summary = new MultiLingual();
                                summary.Language = item.Language;
                                summary.Value = item.Summary;

                                fullCourse.Summaries.Add(summary);
                            }

                            foreach (var item in foundCourse.Contributors)
                            {
                                ContributorCredentials contributor = new ContributorCredentials();
                                contributor.UserId = item.UserId;
                                contributor.Username = item.Username;
                                contributor.Name = item.Name;
                                contributor.Contribution = item.Contribution;
                                if (item.Lector != null)
                                {
                                    contributor.Lector = item.Lector.Value;
                                }

                                fullCourse.Contributors.Add(contributor);
                            }

                            return fullCourse;
                        }
                    }
                }
                catch (Exception exc)
                {
                    Logger.LoggError(exc);
                }
            }

            return null;
        }

        public List<UserShort> GetUsers(string accessKey)
        {
            if (ValidAccesskey(accessKey))
            {
                try
                {
                    using (unwisesourceEntities entity = new unwisesourceEntities())
                    {
                        var users =
                            from user in entity.Users
                            select new UserShort()
                            {
                                UserId = user.UserId,
                                Username = user.Username,
                                Name = user.Name
                            };

                        return users.ToList();
                    }
                }
                catch (Exception exc)
                {
                    Logger.LoggError(exc);
                }
            }

            return null;
        }

        public List<Levels> GetCourseLevels(string accessKey)
        {
            if (ValidAccesskey(accessKey))
            {
                try
                {
                    using(unwisesourceEntities entity = new unwisesourceEntities())
                    {
                        //((IObjectContextAdapter)entity).ObjectContext.Detach(entity.Levels);
                        var levels =
                            from level in entity.Levels
                            select new
                            {
                                LevelId = level.LevelId,
                                LevelName = level.LevelName
                            };

                        List<Levels> result = new List<Levels>();
                        foreach (var item in levels)
                        {
                            //((IObjectContextAdapter)entity).ObjectContext.Detach(level);
                            Levels level = new Levels();
                            level.LevelId = item.LevelId;
                            level.LevelName = item.LevelName;

                            result.Add(level);
                        }

                        return result;
                    }
                }
                catch (Exception exc)
                {
                    Logger.LoggError(exc);
                }
            }

            return null;
        }
    }

    
}
